home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
surfsrc3.zip
/
SHADING.INC
< prev
next >
Wrap
Text File
|
1991-09-25
|
7KB
|
204 lines
{
From: SKYBLU::ENNS 5-FEB-1988 22:17
To: LOWEY
Subj: surf fix
This fix performs the shading calculations without converting them to
normalized coordinates first. This speeds up the shading calculations
but still provide the same results.
Provided to Kevin Lowey by Steve Enns of the University of Saskatchewan,
ENNS@SASK.BITNET
}
{ type vector = array[1..3] of real; }
procedure NORMAL (var V: vector);
{ normalize the vector V }
var Vmag: real; { magnitude of the vector }
J: integer; { index }
begin
Vmag := sqrt (sqr (V[1]) + sqr (V[2]) + sqr (V[3]) );
if (Vmag > 0.0) then
for J := 1 to 3 do
V[J] := V[J] / Vmag;
end; { procedure NORMAL }
function POWER (X, P: real): real;
{ Raise real number X to the power P }
begin
if (X > 0) then
if (P > 0) then
POWER := exp (P * ln(X))
else if (P = 0) then
POWER := 1.0
else
POWER := 1.0 / exp (-P * ln(X))
else if (X = 0) then
POWER := 0.0
else
{ Forget the negatives; aren't dealing with complex nos. }
POWER := 0.0;
end; { function POWER }
{ Common variable for SETSHADE and SHADING }
var S: array[1..MAXLITE] of vector; { light source vectors }
procedure SETSHADE;
{ Set up the light source vectors for the shading routine }
var Lite: integer;
begin
for Lite := 1 to Nlite do begin
S[Lite][1] := Xlite[Lite] - Xfocal;
S[Lite][2] := Ylite[Lite] - Yfocal;
S[Lite][3] := Zlite[Lite] - Zfocal;
normal (S[Lite]);
end;
end; { procedure SETSHADE }
function SHADING (Surf: word; Side: integer): real;
{ Calculate the shade of surface Surf at point (X,Y,Z).
(Returns a negative shade if surface is totally invisible
[facing away from eye] )
Side 1 is the primary side of the surface (assumes the nodes are
numbered counter-clockwise when viewed from the outside of the
surface). Side 2 is the inside, necessary for viewing surfaces
that can be seen from either side (such as function plots).
}
var A: vector; { vector from 1st to 2nd node of surface }
B: vector; { vector from 1st to 3rd node of surface }
N: vector; { vector normal to surface }
E: vector; { vector from 1st node to eye }
D: vector; { difference from source to surface normal }
R: vector; { vector from 1st node to reflected light }
J: integer; { index }
Node1: word; { 1st node # }
Node2: word; { 2nd node # }
Node3: word; { 3rd node # }
Vmag: real; { magnitude of vector, reflected lite to eye }
Cumshade: real; { cumulative shade (from multiple light sources)}
Lite: integer; { light source number }
CosN: real; { cosine of angle from light to surface normal }
CosS: real; { cosine of angle from reflected light to eye }
begin
{$ifdef BIGMEM}
with ptra^ do with ptrb^ do with ptrc^ do with ptri^ do
begin
{$endif}
if (Side = 1) then begin
Node1 := Konnec (Surf, 1);
Node2 := Konnec (Surf, 2);
Node3 := Konnec (Surf, 3);
end else begin
Node1 := Konnec (Surf, 1);
Node2 := Konnec (Surf, 3);
Node3 := Konnec (Surf, 2);
end;
A[1] := Xworld[Node2] - Xworld[Node1];
A[2] := Yworld[Node2] - Yworld[Node1];
A[3] := Zworld[Node2] - Zworld[Node1];
B[1] := Xworld[Node3] - Xworld[Node1];
B[2] := Yworld[Node3] - Yworld[Node1];
B[3] := Zworld[Node3] - Zworld[Node1];
{ Vector cross product N = A X B }
N[1] := A[2]*B[3] - A[3]*B[2];
N[2] := A[3]*B[1] - A[1]*B[3];
N[3] := A[1]*B[2] - A[2]*B[1];
normal(N);
E[1] := Xeye - Xworld[Node1];
E[2] := Yeye - Yworld[Node1];
E[3] := Zeye - Zworld[Node1];
normal(E);
{ Is surface visible to eye? }
if (E[1]*N[1] + E[2]*N[2] + E[3]*N[3] < 0.0) then
Shading := -1.0
else begin
Cumshade := Ambient[Matl[Surf]];
for Lite := 1 to Nlite do begin
for J := 1 to 3 do
D[J] := S[Lite][J] - N[J];
{ Does surface face away from light source? }
CosN := S[Lite][1]*N[1] + S[Lite][2]*N[2] + S[Lite][3]*N[3];
if (CosN < 0.0) then
{ Cumshade := Cumshade + 0.0;} { this light source doesn't contribute}
else begin
for J := 1 to 3 do
R[J] := N[J] - D[J];
normal(R);
{ Find magnitude of vector from reflected light to eye (divided by 2) }
Vmag := sqrt (sqr(E[1]-R[1]) + sqr(E[2]-R[2]) + sqr(E[3]-R[3])) / 2.0;
if (Vmag > 1.0) then
Vmag := 1.0;
CosS := 1.0 - sqr(Vmag);
Cumshade := Cumshade + Intensity[Lite] * (R1[Matl[Surf]] *
power(CosS, R2[Matl[Surf]]) + R3[Matl[Surf]] * CosN);
end; { if sqr(D[1]... }
end; { for Lite }
Shading := Cumshade;
end; { if sqr(E[1]... }
{$ifdef BIGMEM}
end; {with}
{$endif}
end; { function SHADING }
function VISIBLE (Surf: word; Side: integer): boolean;
{ Determine visibility of surface #Surf. If visible, return TRUE.
If invisible, return FALSE.
}
var A: vector; { vector from 1st to 2nd node of surface }
B: vector; { vector from 1st to 3rd node of surface }
N: vector; { vector normal to surface }
E: vector; { vector from 1st node to eye }
Node1: word; { 1st node # }
Node2: word; { 2nd node # }
Node3: word; { 3rd node # }
begin
{$ifdef BIGMEM}
with ptra^ do with ptrb^ do with ptrc^ do
begin
{$endif}
if (Side = 1) then begin
Node1 := Konnec (Surf, 1);
Node2 := Konnec (Surf, 2);
Node3 := Konnec (Surf, 3);
end else begin
Node1 := Konnec (Surf, 3);
Node2 := Konnec (Surf, 2);
Node3 := Konnec (Surf, 1);
end;
A[1] := Xworld[Node2] - Xworld[Node1];
A[2] := Yworld[Node2] - Yworld[Node1];
A[3] := Zworld[Node2] - Zworld[Node1];
B[1] := Xworld[Node3] - Xworld[Node1];
B[2] := Yworld[Node3] - Yworld[Node1];
B[3] := Zworld[Node3] - Zworld[Node1];
{ Vector cross product N = A X B }
N[1] := A[2]*B[3] - A[3]*B[2];
N[2] := A[3]*B[1] - A[1]*B[3];
N[3] := A[1]*B[2] - A[2]*B[1];
{ normal(N); ******* Not required }
E[1] := Xeye - Xworld[Node1];
E[2] := Yeye - Yworld[Node1];
E[3] := Zeye - Zworld[Node1];
{ normal(E); ******* Not required }
{ Is surface visible to eye? }
if (E[1]*N[1] + E[2]*N[2] + E[3]*N[3] < 0.0) then
Visible := FALSE
else
Visible := TRUE;
{$ifdef BIGMEM}
end; {with}
{$endif}
end; { function VISIBLE }